#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef USE_DSPLIB
  #include "src/DSP_mat_mul/DSP_mat_mul.h"
#endif

// Random matrix fill
void matfill(int size, short *mat)
{
  int i, j;
  for (i = 0; i < size; i++)
  {
    for (j = 0; j < size; j++)
    {
      mat[j+size*i] = (short) (rand() % 100);
    }
  }
}

void printmat(int size, short *mat)
{
#if 0
  int i, j;
  for (i = 0; i < size; i++)
  {
    for (j = 0; j < size; j++)
    {
      printf("%6d ", short[i*size + j]);
    }
    printf("\n");
  }
#endif
}

// Matrix multiply using Fixed point C64x+ DSPLib function
void matmult(int size, int shift, short *A, short *B, short *C)
{
#ifdef USE_DSPLIB
  DSP_mat_mul( A,size,size,
               B,     size,
               C,
               shift );
#else
  int i, j, k;
  int sum;
  for (i = 0; i < size; i++)
  {
    for (j = 0; j < size; j++)
    {
      sum = 0;
      for (k = 0; k < size; k++)
      {
        sum += (A[i*size + k] * B[k*size  + j]);
      }
      C[i*size + j] = sum >> shift;
    }
  }
#endif
}

//square matrices only
int main(int argc, char *argv[])
{
  short *A, *B, *C;
  int matsize, shift;
  time_t t;

  if (argc != 2) exit(-1);

  matsize = atoi(argv[1]);
  
  shift = 0;
  while ((matsize>>shift) > 0)
  {
    ++shift;
  }
    
  srand(time(NULL));  

  if (matsize == 0) exit(-1);

  // Allocate space for matrices
  A = calloc(matsize*matsize, sizeof(short));
  matfill(matsize, A);

  B = calloc(matsize*matsize, sizeof(short));
  matfill(matsize, B);
  
  C = calloc(matsize*matsize, sizeof(short));
  
  // Perform multiply and time it
  t = time(NULL);
  matmult(matsize, shift, A, B, C);
  t = time(NULL) - t;
  printf("time of multiply: %d seconds\n",(int)t);

#if 0
  printf("\nmatrix A:\n");
  printmat(matsize, A);

  printf("\nmatrix B:\n");
  printmat(matsize, B);

  printf("\nmatrix C:\n");
  printmat(matsize, C);
#endif
  
  // Free allocated spaces
  free(A);
  free(B);
  free(C);
}
